﻿using System.Configuration;
using System.Xml;
using System.Collections;
using RAP.Framework.Libary.Utils;
using System.IO;
using System;

namespace RAP.Framework.Libary.Configuration
{
  /// <summary>
  /// 站点配置管理
  /// </summary>
  public class ConfigurationManager : DynamicHashtable, IConfigurationManager
  {
    private static IConfigurationManager? _instance = null;
    public static string CONFIG_SECTION_NAME = "ConfigureManager";
    public static string CACHE_KEY = "ConfigurationCache";

    /// <summary>
    /// 获取站点配置管理的全局单太实例，键值对对象
    /// </summary>
    public static IConfigurationManager AppSettings
    {
      get
      {
        if (_instance == null)
        {
          _instance = new ConfigurationManager();
        }
        return _instance;
      }
    }

    private ConfigurationManager()
    {
      if (_instance != null)
      {
        throw new Exception("ConfigurationManager已经实例化！");
      }
    }

    /// <summary>
    /// 当站点参数发生变更时的事件
    /// </summary>
    public event EventHandler? OnSettingsChangedEvent;

    /// <summary>
    /// 当站点参数文件发生变更时的事件
    /// </summary>
    public event EventHandler? OnRefreshingConfigEvent;

    /// <summary>
    /// 发生错误的事件
    /// </summary>
    public event Action<Exception, IDictionary>? OnErrorEvent;

    /// <summary>
    /// 读取.json配置
    /// </summary>
    /// <param name="file">相对路径</param>
    /// <param name="enableWatcher">是否开启文件变更检测</param>
    /// <returns></returns>
    public IConfigurationManager Config(string file, bool enableWatcher = true)
    {
      file.MapPath().ReadJSON(this);
      if (enableWatcher)
      {
        //开启文件监视
        FileInfo fileInfo = file.FileInfo();
        if (fileInfo == null || fileInfo.DirectoryName == null)
        {
          return this;
        }
        FileSystemWatcherUtils.RegisterWatcher(fileInfo.DirectoryName
          , fileInfo.Name
          , NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.Size
          , (watcherInfo, eventArgs) =>
        {
          if (eventArgs.ChangeType == WatcherChangeTypes.Changed)
          {
            OnRefreshingConfigEvent?.Invoke(this, new EventArgs());
            try
            {
              eventArgs.FullPath.ReadJSON(this, true);//文件发生更改时重新读取配置文件
              OnSettingsChangedEvent?.Invoke(this, new EventArgs());
            }
            catch (Exception e)
            {
              if (OnErrorEvent != null)
              {
                OnErrorEvent(e, new Hashtable() { { "File", eventArgs.FullPath.UnMapPath() } });
              }
            }
            finally { }
          }
        });
      }
      return this;
    }

  }
}
